home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sound Fx
/
Sound Fx.iso
/
Software
/
UNZIPED
/
MPW181-5
/
_SETUP.1
/
maplay.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-19
|
10KB
|
373 lines
/* maplay.cpp - MPEG audio decoder
Changes to original maplay 1.2, made by Jeff Tsay:
- Header, bitstream, and miscellaneous flags come from main program
- CRC and range check violations ignored.
- Playtime not printed
- Before every frame, maplay checks if the user has asked it to
stop or seek, which will be reflected in the maplay_args. Every
16 frames a message is sent to the parent telling it which frame
maplay is decoding. All this stuff is synchronized using a mutex.
- Eliminated reading of crc from maplay_args.
- Layer III decoder object used for layer III frames. */
/*
* @(#) maplay.cc 1.20, last edit: 6/22/94 12:32:55
* @(#) Copyright (C) 1993, 1994 Tobias Bading (bading@cs.tu-berlin.de)
* @(#) Berlin University of Technology
*
* Many thanks for ideas and implementations to:
* -> Jim Boucher (jboucher@flash.bu.edu)
* for his idea and first implementation of 8 kHz u-law output
* -> Louis P. Kruger (lpkruger@phoenix.princeton.edu)
* for his implementation of the LinuxObuffer class
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Changes from version 1.1 to 1.2:
* - minor changes to create a LinuxObuffer object
* - minor changes for a u-law version, which creates 8 kHz u-law output
* on an amd device or in stdout mode, if compiled with ULAW defined
* - option -amd forces maplay to treat /dev/audio as an amd device
* in the u-law version. This is helpful on some SPARC clones.
* - iostreams manipulator calls like "cerr << setw (2) << ..." replaced by
* "cerr.width (2); ..." due to problems with older GNU C++ releases.
*/
#ifdef __WIN32__
#define STRICT
#include <windows.h>
#include "mp2win.h"
#else
// other operating system includes
#endif // __WIN32__
#ifndef GUI
#include <iostream.h> // for reporting errors
#endif // GUI
#include "all.h"
#include "crc.h"
#include "header.h"
#include "subband.h"
#include "sublay1.h"
#include "sublay2.h"
#include "synfilt.h"
#include "ibitstr.h"
#include "obuffer.h"
#include "args.h"
#include "layer3.h"
#ifdef SEEK_STOP
#include "mutx_imp.h"
#endif
SynthesisFilter *filter1 = NULL, *filter2 = NULL;
Obuffer *buffer = NULL;
LayerIII_Decoder *l3decoder = NULL;
#pragma argsused
void maplay_Exit(uint32 returncode)
{
#ifdef SEEK_STOP
if ((returncode == 1) && buffer) {
buffer->set_stop_flag();
}
#endif // SEEK_STOP
delete buffer;
buffer = NULL;
delete filter1;
filter1 = NULL;
delete filter2;
filter2 = NULL;
delete l3decoder;
l3decoder = NULL;
}
uint32 maplay(MPEG_Args *maplay_args)
{
uint32 layer;
enum e_mode mode;
BOOL read_ready = FALSE, write_ready = FALSE;
// These arguments should not change while decoding
Crc16 *crc = NULL;
Ibitstream *stream = maplay_args->stream;
Header *header = maplay_args->MPEGheader;
enum e_channels which_channels = maplay_args->which_c;
#ifdef SEEK_STOP
_Mutex mutex = maplay_args->mutex;
#endif
#ifdef WIN32GUI
HWND hWnd = maplay_args->hWnd;
#else
// copy your operating system dependent arguments here
#endif // WIN32GUI
// get info from header of first frame:
layer = header->layer();
if ((mode = header->mode()) == single_channel)
which_channels = left;
// create filter(s):
{
real scalefactor = (maplay_args->use_own_scalefactor) ?
maplay_args->scalefactor :
32768.0;
filter1 = new SynthesisFilter(0, scalefactor);
if ((mode != single_channel) && (which_channels == both))
filter2 = new SynthesisFilter(1, scalefactor);
}
// create buffer, and check to see if created ok:
buffer = (maplay_args->stdout_mode) ?
create_stdout_obuffer(maplay_args) :
create_obuffer(maplay_args);
if (buffer == NULL) {
maplay_Exit(0);
return(1);
}
// Layer III : initialize decoder
if (layer == 3)
l3decoder = new LayerIII_Decoder(stream, header,
filter1, filter2,
buffer, which_channels);
do
{
#ifdef SEEK_STOP
mtx_lock(mutex);
if (maplay_args->stop) {
maplay_Exit(1);
mtx_unlock(mutex);
return(0);
}
if (maplay_args->position_change) {
buffer->clear_buffer();
if (!header->stream_seek(stream, maplay_args->desired_position)) {
maplay_Exit(0);
mtx_unlock(mutex);
return(1);
}
maplay_args->position_change = FALSE;
if (l3decoder)
l3decoder->seek_notify();
// notify the parent of the current position
#ifdef WIN32GUI
PostMessage(hWnd, SEEK_ACK, NULL, NULL);
PostMessage(hWnd, SCROLL_POS, stream->current_frame(), 0);
#else
#endif // WIN32GUI
}
// Send notification to the scroll bar every 16 frames
{
int32 cf = stream->current_frame();
if (!(cf & 0xf) && !(maplay_args->stop)) {
// Notify the parent of the current position
#ifdef WIN32GUI
PostMessage(hWnd, SCROLL_POS, cf, 0);
#else
#endif // WIN32GUI
}
mtx_unlock(mutex);
}
#endif // SEEK_STOP
// is there a change in important parameters?
// (bitrate switching is allowed)
if (header->layer() != layer)
{
// layer switching is allowed
if (header->layer() == 3) {
l3decoder = new LayerIII_Decoder(stream, header,
filter1, filter2,
buffer, which_channels);
} else if (layer == 3) {
delete l3decoder;
l3decoder = NULL;
}
layer = header->layer();
}
if (layer != 3) {
Subband *subbands[32];
uint32 num_subbands = header->number_of_subbands();
mode = header->mode();
// create subband objects:
if (layer == 1)
{
if (mode == single_channel)
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1(i);
else if (mode == joint_stereo) {
uint32 i;
for (i = 0; i < header->intensity_stereo_bound(); ++i)
subbands[i] = new SubbandLayer1Stereo(i);
for (; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1IntensityStereo(i);
} else {
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer1Stereo(i);
}
} else { // Layer II
if (mode == single_channel)
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer2(i);
else if (mode == joint_stereo)
{
uint32 i;
for (i = 0; i < header->intensity_stereo_bound(); ++i)
subbands[i] = new SubbandLayer2Stereo(i);
for (; i < num_subbands; ++i)
subbands[i] = new SubbandLayer2IntensityStereo(i);
} else {
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i] = new SubbandLayer2Stereo(i);
}
}
// start to read audio data:
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i]->read_allocation(stream, header, crc);
if (layer == 2)
for (uint32 i = 0; i < num_subbands; ++i)
((SubbandLayer2 *)subbands[i])->read_scalefactor_selection(stream,
crc);
if (!crc || header->checksum_ok())
{
// no checksums or checksum ok, continue reading from stream:
for (uint32 i = 0; i < num_subbands; ++i)
subbands[i]->read_scalefactor(stream, header);
do
{
for (uint32 i = 0; i < num_subbands; ++i)
read_ready = subbands[i]->read_sampledata(stream);
do
{
for (uint32 i = 0; i < num_subbands; ++i)
write_ready = subbands[i]->put_next_sample(which_channels,
filter1, filter2);
filter1->calculate_pcm_samples(buffer);
if ((which_channels == both) && (mode != single_channel))
filter2->calculate_pcm_samples(buffer);
} while (!write_ready);
} while (!read_ready);
buffer->write_buffer(1);
} // checksum ok
// Jeff : Don't let user know if crc violated.
// else
// Sh*t! Wrong crc checksum in frame!
// cerr << "WARNING: frame contains wrong crc checksum! (throwing frame away)\n";
for (uint32 i = 0; i < num_subbands; ++i) {
delete subbands[i];
}
} else { // Layer III
l3decoder->decode();
}
}
while (header->read_header(stream, &crc));
quit:
#ifdef SEEK_STOP
mtx_lock(mutex);
if (!maplay_args->stop) {
// notify the parent of the last frame
#ifdef WIN32GUI
PostMessage(hWnd, SCROLL_POS, stream->current_frame(), 0);
#else
#endif // WIN32GUI
}
#endif // SEEK_STOP
maplay_Exit(0);
#ifdef SEEK_STOP
maplay_args->done = TRUE;
if (!maplay_args->stop) {
// tell the parent that we are done
#ifdef WIN32GUI
PostMessage(hWnd, WM_THREADEND, NULL, NULL);
#else
#endif // WIN32GUI
}
mtx_unlock(mutex);
#endif // SEEK_STOP
return(0);
}